﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace LPTModule
{
    static class LPTSearcher
    {
        [DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")]
        public static extern int RegQueryValueEx(uint hKey, char[] lpValueName, int lpReserved,
        ref int lpType, ref byte lpData, ref int lpcbData);
        [DllImport("advapi32.dll", EntryPoint = "RegOpenKey")]
        public static extern int RegOpenKeyEx(uint hKey, char[] lpSubKey, ref uint phkResult);

        static string TempPortName;
        public class LPTInfo
        {
            public string name;
            public int portnum;
            public LPTInfo(string n, int pn)
            {
                name = n;
                portnum = pn;
            }

        }

        static List<LPTInfo> LPTPortsD = new List<LPTInfo>();
        public static List<LPTInfo> LPTPorts
        {
            get { return LPTPortsD; }
        }

        public static bool Find(string CurPath)
        {
            try
            {

                RegistryKey rk = Registry.LocalMachine.OpenSubKey(CurPath);
                object PortName = rk.GetValue("portName");
                if (PortName != null)
                {
                    if ((PortName.GetType() == "a".GetType()) &&
                       (((string)PortName).IndexOf("LPT") == 0))
                    {
                        TempPortName = (string)PortName;
                        return true;
                    }
                }

                if (rk.SubKeyCount != 0)
                {
                    string[] Paths = rk.GetSubKeyNames();
                    bool f = false;
                    foreach (string s in Paths)
                        f |= (s == "Control");


                    foreach (string s in Paths)
                    {
                        if (Find(CurPath + "\\" + s) && f)
                        {
                            RegistryKey rk2 = rk.OpenSubKey("Control");
                            if (!(Array.IndexOf(rk2.GetValueNames(), "AllocConfig") != -1)) break;
                            uint hid = 0;
                            char[] CharAddr = new char[1000];
                            string Control = CurPath + "\\Control";
                            Control.CopyTo(0, CharAddr, 0, Control.Length);
                            int r1 = RegOpenKeyEx(0x80000002, CharAddr, ref hid);

                            string AllocConfig = "AllocConfig\0";
                            AllocConfig.CopyTo(0, CharAddr, 0, AllocConfig.Length);
                            byte[] Data = new byte[1000];
                            int aaa = 8, b = 1000;
                            int r2 = RegQueryValueEx(hid, CharAddr, 0, ref aaa, ref Data[0], ref b);

                            int PortAddr = (Data[25] << 8) + Data[24];

                            LPTPortsD.Add(new LPTInfo(TempPortName, PortAddr));
                            //Console.WriteLine(TempPortName + "  :  " + PortAddr.ToString());
                        }
                    }
                }
            }
            catch { };
            return false;
        }

        static bool IsNot = true;

        public static void Start()
        {
            if (IsNot)
            {
                Find(@"SYSTEM\\CurrentControlSet");
                LPTPortsD.Sort(delegate(LPTInfo x, LPTInfo y) { return x.name.CompareTo(y.name); });
                IsNot = false;
            }
        }
    }
}
